<!-- テクスチャへのレンダリングサンプル -->
<html>
<head>
<!-- オフスクリーン用のシェーダー -->
<script id="vshader0" type="x-shader/x-vertex"> 
  attribute vec4 vPosition;
  attribute vec4 vTexCoord;
  varying vec2 texCoord;
  void main()
  {
    gl_Position = vPosition;
    texCoord.xy = vTexCoord.xy;
  }
</script>
 
<script id="fshader0" type="x-shader/x-fragment"> 
#ifdef GL_ES
precision highp float;
#endif
  uniform sampler2D sampler2d;
  varying vec2 texCoord;
  void main()
  {
    gl_FragColor = texture2D(sampler2d, texCoord);
  }
</script>

<!-- 描画サーフェース用のシェーダー -->
<script id="vshader1" type="x-shader/x-vertex"> 
  attribute vec4 vPosition;
  attribute vec4 vTexCoord;
  varying vec2 texCoord;
  void main()
  {
    gl_Position = vPosition;
    // OpenGLは左下原点の座標系のため、テクスチャ座標と上下が反転する
    texCoord.x = vTexCoord.x;
    texCoord.y = 1.0-vTexCoord.y;
  }
</script>
 
<script id="fshader1" type="x-shader/x-fragment"> 
#ifdef GL_ES
precision highp float;
#endif
  uniform sampler2D sampler2d;
  varying vec2 texCoord;
  void main()
  {
    gl_FragColor = texture2D(sampler2d, texCoord);
  }
</script>

<script>
  var cv_width = 0;
  var cv_height = 0;
  var vertint;
  var texint;
  var tex;
  var framebuffer;
  var rendertex;
  var shader0;
  var shader1;
  function init(canvas)
  {
    var gl = canvas.getContext("experimental-webgl");
    if (!gl) {
      alert("Failed to create WebGL context.");
      return null;
    }
    
    // オフスクリーン用のシェーダーをロード
    shader0 = gl.createProgram();
    {
      var vshaderScript = document.getElementById("vshader0");
      var fshaderScript = document.getElementById("fshader0");
      if (!vshaderScript) {
        alert("Failed to get vshaderScript.");
        return null;
      }
      if (!fshaderScript) {
        alert("Failed to get fshaderScript.");
        return null;
      }
      
      var vshader = gl.createShader(gl.VERTEX_SHADER);
      var fshader = gl.createShader(gl.FRAGMENT_SHADER);
      if (!vshader || !fshader) {
        alert("Failed to createShader().");
        return null;
      }
      
      gl.shaderSource(vshader, vshaderScript.text);
      gl.shaderSource(fshader, fshaderScript.text);
      
      gl.compileShader(vshader);
      gl.compileShader(fshader);
      
      gl.attachShader(shader0, vshader);
      gl.attachShader(shader0, fshader);
      
      gl.bindAttribLocation(shader0, 0, "vPosition");
      gl.bindAttribLocation(shader0, 1, "vTexCoord");
      
      gl.enableVertexAttribArray(0);  // vPosition
      gl.enableVertexAttribArray(1);  // vTexCoord
      
      gl.linkProgram(shader0);
    }
    
    // 描画サーフェース用のシェーダーをロード
    shader1 = gl.createProgram();
    {
      var vshaderScript = document.getElementById("vshader1");
      var fshaderScript = document.getElementById("fshader1");
      if (!vshaderScript) {
        alert("Failed to get vshaderScript.");
        return null;
      }
      if (!fshaderScript) {
        alert("Failed to get fshaderScript.");
        return null;
      }
      
      var vshader = gl.createShader(gl.VERTEX_SHADER);
      var fshader = gl.createShader(gl.FRAGMENT_SHADER);
      if (!vshader || !fshader) {
        alert("Failed to createShader().");
        return null;
      }
      
      gl.shaderSource(vshader, vshaderScript.text);
      gl.shaderSource(fshader, fshaderScript.text);
      
      gl.compileShader(vshader);
      gl.compileShader(fshader);
      
      gl.attachShader(shader1, vshader);
      gl.attachShader(shader1, fshader);
      
      gl.bindAttribLocation(shader1, 0, "vPosition");
      gl.bindAttribLocation(shader1, 1, "vTexCoord");
      
      gl.enableVertexAttribArray(0);  // vPosition
      gl.enableVertexAttribArray(1);  // vTexCoord
      
      gl.linkProgram(shader1);
    }
    
    gl.clearColor(0, 0, 0, 1);
    gl.clearDepth(1000);
    
    gl.enable(gl.DEPTH_TEST);
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    
    gl.enable(gl.TEXTURE_2D);
    
    tex = gl.createTexture();
    tex.image = new Image();
    tex.image.onload = function() { 
      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, tex);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tex.image);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.bindTexture(gl.TEXTURE_2D, null);	
    }
    tex.image.src = "img.jpg";
    
    var vertices = [
      -1.0, -1.0,  0.0,
      -1.0, +1.0,  0.0,
      +1.0, -1.0,  0.0,
      +1.0, +1.0,  0.0,
    ];
    vertint = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertint);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    vertint.itemSize = 3;
    vertint.numItems = 4;
    
    var texcoords = [
      0, 1,
      0, 0,
      1, 1,
      1, 0,
    ];
    texint = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, texint);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW);
    texint.itemSize = 2;
    texint.numItems = 4;
    
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
    
    // フレームバッファオブジェクトを生成
    framebuffer  = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    {
      framebuffer.width = cv_width;
      framebuffer.height = cv_height;
      rendertex = gl.createTexture();
      {
        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, rendertex);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, cv_width, cv_height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, rendertex, 0);
        gl.bindTexture(gl.TEXTURE_2D, null);
      }
      if (!gl.isFramebuffer(framebuffer)) {
        alert("Failed to create framebuffer object");
      } else {
        console.log("Success to create framebuffer object.");
      }
      var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
      if (status != gl.FRAMEBUFFER_COMPLETE) {
        console.log("status != gl.FRAMEBUFFER_COMPLETE");
      } else {
        console.log("status == gl.FRAMEBUFFER_COMPLETE");
      }
      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    }
    
    return gl;
  }
  
  function reshape(gl)
  {
    var canvas = document.getElementById("myCanvas");
    if (canvas.clientWidth == cv_width
     && canvas.clientHeight == cv_height) {
      return;
    }
    cv_width = canvas.clientWidth;
    cv_height = canvas.clientHeight;
    gl.viewport(0, 0, cv_width, cv_height);
  }
  
  function Render(gl)
  {
    reshape(gl);
    {
      // オフスクリーンレンダリング
      gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
      gl.useProgram(shader0);
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
      
      gl.bindBuffer(gl.ARRAY_BUFFER, vertint);
      gl.vertexAttribPointer(0, vertint.itemSize, gl.FLOAT, false, 0, 0);

      gl.bindBuffer(gl.ARRAY_BUFFER, texint);
      gl.vertexAttribPointer(1, texint.itemSize, gl.FLOAT, false, 0, 0);

      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, tex);
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertint.numItems);
      
      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    }
    
    gl.useProgram(shader1);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    
    gl.bindBuffer(gl.ARRAY_BUFFER, vertint);
    gl.vertexAttribPointer(0, vertint.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, texint);
    gl.vertexAttribPointer(1, texint.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindTexture(gl.TEXTURE_2D, rendertex);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertint.numItems);
    
    gl.flush();
   
  }
  
  function start()
  {
    var canvas = document.getElementById("myCanvas");
    canvas.width = 640;
    canvas.height = 480;
    
    cv_width = canvas.width;
    cv_height = canvas.height;
    
    var gl = init(canvas);
    setInterval(function() { Render(gl) }, 30);
  }
</script> 
</head> 
 
<body onload="start()"> 
<canvas id="myCanvas"> </canvas> 
</body> 
</html> 
